package com.netty.common;

import java.io.RandomAccessFile;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.netty.module.ChatMessage;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedNioFile;
import io.netty.util.CharsetUtil;

import org.apache.commons.lang3.StringUtils;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.DefaultFileRegion;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.handler.codec.http.QueryStringDecoder;

public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
	private final String INDEX = "D:\\Workspaces\\NettyWebSocket\\src\\main\\resources\\static\\http.txt";
	private final String webUri;

	public HttpRequestHandler(String webUri) {
		this.webUri = webUri;
	}

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
		String uri = StringUtils.substringBefore(request.uri(), "?");
		
		if(webUri.equalsIgnoreCase(uri)) {//获取webSocket参数
			QueryStringDecoder query = new QueryStringDecoder(request.uri());
			Map<String, List<String>> map = query.parameters();
			List<String> tokens = map.get("token");
			List<String> tos = map.get("to");

			//根据参数保存当前登录对象, 并把该token加入到channel中
			if(tokens != null && !tokens.isEmpty()) {
				String from = tokens.get(0);
				String to = tos.get(0);
				System.out.println("当前通道数："+ChatConstants.channels.size());
				Channel channel = ctx.channel();
				channel.attr(ChatConstants.CHANNEL_TOKEN_KEY).getAndSet(from);
				ChatConstants.channels.put(from,channel);//保存当前用户通道

				//患者上线时，往医生端推送该患者信息
				//if(to.contains("2")){
					Channel channelto = ChatConstants.channels.get(to);
					if(channelto!=null){
						ChatMessage message = new ChatMessage(from);
						String text = JSON.toJSONString(message,SerializerFeature.DisableCircularReferenceDetect);
						channelto.writeAndFlush(new TextWebSocketFrame(text));
					}
				//}
			}
			request.setUri(uri);
			//如果是websocket请求，则保留数据并传递到下一个ChannelHandler
			ctx.fireChannelRead(request.retain());
		}else if("/bf".equalsIgnoreCase(uri)){
			//返回字符串
			ByteBuf bf = Unpooled.copiedBuffer("服务当前时间："+LocalDateTime.now(),CharsetUtil.UTF_8);
			FullHttpResponse fresponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
					HttpResponseStatus.OK,bf);
			fresponse.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain;charset=UTF-8");
			fresponse.headers().set(HttpHeaderNames.CONTENT_LENGTH,bf.readableBytes());
			ctx.writeAndFlush(fresponse);
		}else if("/file".equalsIgnoreCase(uri)){
			//返回文件内容
			if(HttpUtil.is100ContinueExpected(request)) {
				send100ContinueExpected(ctx);
			}
			RandomAccessFile file = new RandomAccessFile(INDEX, "r");
			HttpResponse response = new DefaultHttpResponse(request.protocolVersion(), HttpResponseStatus.OK);
			response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
			boolean keepAlive = HttpUtil.isKeepAlive(request);
			if(keepAlive) {
				response.headers().set(HttpHeaderNames.CONTENT_LENGTH, file.length());
				response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
				//response.headers().set("Access-Control-Allow-Origin", "*");//http://192.168.1.107:6090
				//response.headers().set("Access-Control-Allow-Methods", "true");
			}
			ctx.write(response);
			if(ctx.pipeline().get(SslHandler.class) == null) {
				ctx.write(new DefaultFileRegion(file.getChannel(), 0, file.length()));
			}else {
				ctx.write(new ChunkedNioFile(file.getChannel()));
			}
			ChannelFuture future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
			if(!keepAlive) {
				future.addListener(ChannelFutureListener.CLOSE);
			}
			file.close();
		}
	}
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		cause.printStackTrace();
		ctx.close();
	}
	
	private void send100ContinueExpected(ChannelHandlerContext ctx) {
		FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONFLICT);
		ctx.writeAndFlush(response);		
	}
}
